package com.bpm.example.event.time;

import com.bpm.common.util.FlowableEngineUtil;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.junit.Before;
import org.junit.Test;

import java.util.List;
import java.util.Map;

/**
 * 定时器开始事件流程演示
 * @author curleyg
 * @version 1.0
 * @date 2020/8/31 16:06
 */
@Slf4j
public class RunTimerStartEventProcessDemo extends FlowableEngineUtil {

    @Before
    public void initFlowableEngineAndServices() {
        initFlowableEngineAndServices("flowable.job.xml");
    }

    @Test
    public void runTimerStartEventProcessDemo1() throws Exception {

        //部署流程（该流程指定时间启动）
        ProcessDefinition procDef
                = deployResource("processes/time/TimerStartEventProcess1.bpmn20.xml");

        //根据流程实例id 查询任务个数
        TaskQuery taskQuery1 = taskService.createTaskQuery()
                .processDefinitionId(procDef.getId());

        log.info("流程实例中任务个数为: {}", taskQuery1.count());

        //断言等于0，
        assert taskQuery1.count() == 0;

        // 暂停90秒
        Thread.sleep(1000 * 90);

        //查询任务个数
        TaskQuery taskQuery2 = taskService.createTaskQuery()
                .processDefinitionId(procDef.getId());

        //断言等于1
        assert taskQuery2.count() == 1;

        log.info("流程实例中任务个数为: {}", taskQuery2.count());
        Task task = taskQuery2.singleResult();
        log.info("当前任务名称为: {}", task.getName());
        //完成任务
        taskService.complete(task.getId());
    }

    @Test
    public void getStartFlowableDataBynstance(){
        String processInstanceId="7";
        //首先我们在ACT_HI_PROCINST中拿到实例id:7
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (historicProcessInstance != null) {
            System.out.println("流程实例ID: " + historicProcessInstance.getId());
            System.out.println("业务主键: " + historicProcessInstance.getBusinessKey());//启动时可设置
            System.out.println("业务状态: " + historicProcessInstance.getBusinessStatus());
            System.out.println("流程定义ID: " + historicProcessInstance.getProcessDefinitionId());//自动生成
            System.out.println("流程定义名称: " + historicProcessInstance.getProcessDefinitionName());//部署时可设置
            System.out.println("流程定义Key: " + historicProcessInstance.getProcessDefinitionKey());//部署时可设置
            System.out.println("流程定义版本: " + historicProcessInstance.getProcessDefinitionVersion());
            System.out.println("部署ID: " + historicProcessInstance.getDeploymentId());
            System.out.println("开始时间: " + historicProcessInstance.getStartTime());
            System.out.println("结束时间: " + historicProcessInstance.getEndTime());
            System.out.println("持续时间(毫秒): " + historicProcessInstance.getDurationInMillis());
            System.out.println("开始节点ID: " + historicProcessInstance.getStartActivityId());
            System.out.println("结束节点ID: " + historicProcessInstance.getEndActivityId());
            System.out.println("启动用户ID: " + historicProcessInstance.getStartUserId());//流程发起式可设置
            System.out.println("删除原因: " + historicProcessInstance.getDeleteReason());
            System.out.println("父流程实例ID: " + historicProcessInstance.getSuperProcessInstanceId());
            System.out.println("租户ID: " + historicProcessInstance.getTenantId());
            System.out.println("流程名称: " + historicProcessInstance.getName());
            System.out.println("流程描述: " + historicProcessInstance.getDescription());
            System.out.println("回调ID: " + historicProcessInstance.getCallbackId());
            System.out.println("回调类型: " + historicProcessInstance.getCallbackType());
            System.out.println("引用ID: " + historicProcessInstance.getReferenceId());
            System.out.println("引用类型: " + historicProcessInstance.getReferenceType());
            System.out.println("阶段传播实例ID: " + historicProcessInstance.getPropagatedStageInstanceId());
            Map<String, Object> vars = historicProcessInstance.getProcessVariables();
            System.out.println("流程变量:");
            vars.forEach((k, v) -> System.out.println(" - " + k + ": " + v));

        }
        //获取执行实例
        List<HistoricActivityInstance> activityInstances = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId)
                .orderByHistoricActivityInstanceStartTime()
                .asc()
                .list();


        for (HistoricActivityInstance hai : activityInstances) {
            System.out.println("====== 活动节点 ======");
            System.out.println("ID: " + hai.getId());
            System.out.println("活动ID: " + hai.getActivityId());
            System.out.println("活动名称: " + hai.getActivityName());
            System.out.println("活动类型: " + hai.getActivityType());
            System.out.println("流程定义ID: " + hai.getProcessDefinitionId());
            System.out.println("流程实例ID: " + hai.getProcessInstanceId());
            System.out.println("执行ID: " + hai.getExecutionId());
            System.out.println("任务ID: " + hai.getTaskId());
            System.out.println("被调用流程实例ID: " + hai.getCalledProcessInstanceId());
            System.out.println("办理人: " + hai.getAssignee());
            System.out.println("开始时间: " + hai.getStartTime());
            System.out.println("结束时间: " + hai.getEndTime());
            System.out.println("持续时间（毫秒）: " + hai.getDurationInMillis());
            System.out.println("事务顺序: " + hai.getTransactionOrder());
            System.out.println("删除原因: " + hai.getDeleteReason());
            System.out.println("租户ID: " + hai.getTenantId());
            System.out.println("=====================");
        }
        List<HistoricTaskInstance> taskList = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).list();

        for (HistoricTaskInstance task : taskList) {
            System.out.println("====== 历史任务 ======");
            System.out.println("ID: " + task.getId());
            System.out.println("名称: " + task.getName());
            System.out.println("描述: " + task.getDescription());
            System.out.println("优先级: " + task.getPriority());
            System.out.println("Owner（所有者）: " + task.getOwner());
            System.out.println("Assignee（办理人）: " + task.getAssignee());
            System.out.println("流程实例ID: " + task.getProcessInstanceId());
            System.out.println("执行ID: " + task.getExecutionId());
            System.out.println("任务定义ID: " + task.getTaskDefinitionId());
            System.out.println("流程定义ID: " + task.getProcessDefinitionId());
            System.out.println("Scope ID: " + task.getScopeId());
            System.out.println("Sub Scope ID: " + task.getSubScopeId());
            System.out.println("Scope Type: " + task.getScopeType());
            System.out.println("Scope Definition ID: " + task.getScopeDefinitionId());
            System.out.println("传播阶段实例ID: " + task.getPropagatedStageInstanceId());
            System.out.println("创建时间: " + task.getCreateTime());
            System.out.println("任务定义KEY: " + task.getTaskDefinitionKey());
            System.out.println("到期时间: " + task.getDueDate());
            System.out.println("分类: " + task.getCategory());
            System.out.println("父任务ID: " + task.getParentTaskId());
            System.out.println("租户ID: " + task.getTenantId());
            System.out.println("表单KEY: " + task.getFormKey());

            System.out.println("删除原因: " + task.getDeleteReason());
            System.out.println("开始时间（已废弃）: " + task.getStartTime());  // 已废弃
            System.out.println("结束时间: " + task.getEndTime());
            System.out.println("持续时间（毫秒）: " + task.getDurationInMillis());
            System.out.println("工作耗时（毫秒）: " + task.getWorkTimeInMillis());
            System.out.println("认领时间: " + task.getClaimTime());

            Map<String, Object> taskVars = task.getTaskLocalVariables();
            System.out.println("任务局部变量: " + (taskVars != null ? taskVars : "{}"));

            Map<String, Object> procVars = task.getProcessVariables();
            System.out.println("流程变量: " + (procVars != null ? procVars : "{}"));

            Map<String, Object> caseVars = task.getCaseVariables();
            System.out.println("Case变量: " + (caseVars != null ? caseVars : "{}"));

            System.out.println("候选人/参与人列表: ");
//            if (task.getIdentityLinks() != null) {
//                task.getIdentityLinks().forEach(link -> {
//                    System.out.println(" - 类型: " + link.getType() + ", 用户: " + link.getUserId() + ", 组: " + link.getGroupId());
//                });
//            }

            System.out.println("=====================");
        }
    }

    @Test
    public void runTimerStartEventProcessDemo2() throws Exception {
        //部署流程（该流程每一分钟启动一次）
        ProcessDefinition procDef
                = deployResource("processes/time/TimerStartEventProcess2.bpmn20.xml");

        //根据流程实例id 查询任务个数
        TaskQuery taskQuery1 = taskService.createTaskQuery()
                .processDefinitionId(procDef.getId());

        log.info("流程实例中任务个数为: {}", taskQuery1.count());

        //断言等于0，
        assert taskQuery1.count() == 0;

        // 暂停90秒
        Thread.sleep(1000 * 90);

        //查询任务个数
        TaskQuery taskQuery2 = taskService.createTaskQuery()
                .processDefinitionId(procDef.getId());

        //断言等于1
        assert taskQuery2.count() == 1;

        log.info("流程实例中任务个数为: {}", taskQuery2.count());
        Task task = taskQuery2.singleResult();
        log.info("当前任务名称为: {}", task.getName());
        //完成任务
        taskService.complete(task.getId());
    }


    @Test
    public void runTimerStartEventProcessDemo3() throws Exception {
        //部署流程（该流程每一分钟启动一次）
        ProcessDefinition procDef
                = deployResource("processes/time/TimerStartEventProcess3.bpmn20.xml");

        //根据流程实例id 查询任务个数
        TaskQuery taskQuery1 = taskService.createTaskQuery()
                .processDefinitionId(procDef.getId());

        log.info("流程实例中任务个数为: {}", taskQuery1.count());

        // 暂停90秒
        Thread.sleep(1000 * 60);

        //查询任务个数
        TaskQuery taskQuery2 = taskService.createTaskQuery()
                .processDefinitionId(procDef.getId());
        log.info("流程实例中任务个数为: {}", taskQuery2.count());
        List<Task> task = taskQuery2.list();
        task.forEach(e->{
            log.info("当前任务名称为: {}", e.getName());
            //完成任务
            taskService.complete(e.getId());
        });

    }
}
